#pragma once

#include "StringConst.h"

#include <stdarg.h>

namespace Pan
{

   /**
    * @brief 字符串缓冲区
    */
   class StringBuffer : public StringConst
   {

   public:
      /**
       * @brief StringBuffer构造函数
       * @param buffer_size 缓冲区大小
       */
      StringBuffer(unsigned long buffer_size = 512, wchar_t *buffer = nullptr);

      // 复制构造
      StringBuffer(const StringBuffer &sb);

      // 移动构造
      StringBuffer(StringBuffer &&sb);

      /**
       * @brief ~StringBuffer
       */
      ~StringBuffer();

   protected:
      // 是否为外部缓冲区
      const bool _is_out_buffer;

      /**
       * @brief 容量, 也就是缓冲区的大小
       */
      const unsigned long _buffer_size;

      /**
       * @brief 字符串结束符所在的下标
       */
      unsigned long _end;

   public:
      inline wchar_t *buffer() const { return const_cast<wchar_t *>(this->_p); }

   public:
      inline const wchar_t *cstring() const { return this->_p; };

   public:
      /**
       * @brief 取得字符的结束位置, 以指针的方式返回
       * @return 一个指向字符串结束符的指针
       */
      inline wchar_t *pointer_end() const { return this->buffer() + this->_end; }

   public:
      /**
       * @brief 判断缓冲区指针是否为空
       * @return bool值
       */
      inline bool is_nullptr() const { return this->_p == nullptr; }

   public:
      // 是否外部缓冲区
      inline bool is_buffer_out() const { return this->_is_out_buffer; }

   public:
      inline unsigned long buffer_size() const { return this->_buffer_size; }

   public:
      // 缓冲区剩余空间
      inline unsigned long buffer_size_free() const { return this->_buffer_size - this->_end - 1; }

   public:
      inline unsigned long buffer_bytes() const { return this->_buffer_size * sizeof(wchar_t); }

   public:
      /**
       * @brief 移除字符串尾部指定的字符
       * @param ch 指定的字符
       * @return 如果最后一个字符是指定字符，返回true；否则返回false。
       */
      bool remove_tail_char(wchar_t ch);

   public:
      bool append_tail_char(wchar_t ch);

   public:
      /**
       * @brief 设置字符串的长度
       * @param len 字符串的新长度
       * @return 是否设置成功
       */
      inline void set_length(unsigned long len)
      {
         this->_end = len % this->_buffer_size;
         this->buffer()[this->_end] = L'\0';
      }

   public:
      /**
       * @brief 取得字符串的长度
       * @return 字符串的长度
       */
      inline unsigned long length() const { return this->_end; }

   public:
      /**
       * @brief 重新计算字符串的长度
       * @return 字符串的长度
       */
      unsigned long calc_length();

   public:
      /**
       * @brief 清空缓冲区
       * @param all 是否全部清空
       */
      void clear(bool all = false);

   public:
      /**
       * @brief 将指定字符串复制到缓冲区
       * @param str
       */
      void copy_from(const wchar_t *str);

   public:
      void format(const wchar_t *_format, ...);

   public:
      void format2(const wchar_t *_format, va_list va);

   public:
      /**
       * @brief 拼接指定字符到缓冲区的尾部
       * @param str 字符串
       */
      void append(const wchar_t *str);

      /**
       * @brief 添加一个字符
       */
      void append(const wchar_t ch);

      // 操作符重载
   public:
      // 赋值
      inline StringBuffer &operator=(const wchar_t *str)
      {
         this->copy_from(str);
         return *this;
      }

      // 拼接字符串
      inline StringBuffer &operator+=(const wchar_t *str)
      {
         this->append(str);
         return *this;
      }

      // 拼接字符
      inline StringBuffer &operator+=(const wchar_t ch)
      {
         this->append(ch);
         return *this;
      }

      inline StringBuffer &operator<<(wchar_t ch)
      {
         this->append(ch);
         return *this;
      }

      // 拼接字符串
      inline StringBuffer &operator<<(const wchar_t *str)
      {
         this->append(str);
         return *this;
      }

      inline StringBuffer &operator<<(const StringBuffer &s)
      {
         this->append(s.cstring());
         return *this;
      }
   };

} // namespace Pan
